﻿#pragma once

//#ifndef MusicReader_H
//	#define MusicReader_H
#include "common.h"

extern "C" {
	// include FFmpeg library
	// 解码器
	#include <libavformat/avformat.h>
	#include <libavcodec/avcodec.h>
	#include <libavutil/avutil.h>
	#include <libswresample/swresample.h>
	#include <libavutil/opt.h>
	#include <libavutil/channel_layout.h>
	#include <libavutil/samplefmt.h>
	//#include <libswresample/swresample_internal.h>

	// 滤镜
	#include <libavutil/audio_fifo.h>
	#include <libavfilter/avfilter.h>
	#include <libavfilter/buffersrc.h>
	#include <libavfilter/buffersink.h>
}

#ifndef MUSICREADER_H
	#define MUSICREADER_H  // 在头文件中声明一次即可

// include C++ library
//#include <cstdio>
//#include <cstring>
//#include <string>
//#include <mutex>
//#include <stdexcept>

// include Qt library
//#include <QDebug>
//#include <QObject>

// 打开文件失败
//class OpenFileError : public std::runtime_error {
//public:
//	OpenFileError(const std::string& msg) : std::runtime_error(msg) {}
//};
extern int open_file_error;

// define struct for filters
struct MyFilter {
	MyFilter() = default;
	MyFilter(float in_f62, float in_f125, float in_f250, float in_f500, float in_f1000,
		float in_f2000, float in_f4000, float in_f8000,
		float in_f160000)
		: f62(in_f62), f125(in_f125), f250(in_f250)
		, f500(in_f500), f1000(in_f1000), f2000(in_f2000)
		, f4000(in_f4000), f8000(in_f8000), f16000(in_f160000) {}

	float f62, f125, f250,
		  f500, f1000, f2000,
		  f4000, f8000, f16000;
};
extern MyFilter my_filters;

// define struct for PCM format
struct InPCMFormat {
	InPCMFormat() = default;
	InPCMFormat(int channels = 2,
		int sample_rate = 44100,
		std::string sample_fmt = "s16");

	// 设置 PCM 解码器
	void set_reader_pcm_format(AVCodecContext* p_codec_context) {
		p_codec_context->ch_layout = pcm_layout;
		p_codec_context->sample_rate = pcm_sample_rate;
		p_codec_context->request_sample_fmt = pcm_sample_fmt;
	}
	void set_in_pcm_format(int channels = 2,
		int sample_rate = 44100,
		std::string sample_fmt = "s16");

	std::string format_string();

	AVChannelLayout  pcm_layout;
	int				 pcm_sample_rate;
	AVSampleFormat	 pcm_sample_fmt;
};
extern InPCMFormat in_pcm_format;
extern bool is_pcm_format_set_successfully;

// define constants

class MusicReader/* : public QObject*/
{
	//Q_OBJECT // 继承自 QObject，如果需要作为 QObject 的子类使用 pcm 文件流

public: // public functions
	//MusicReader(const MusicReader&) = delete;
	MusicReader() = default;
	MusicReader(const std::string& filename);
	~MusicReader();

	inline void free_ffmpeg();

	void init_filters(
		AVChannelLayout layout = AV_CHANNEL_LAYOUT_MONO,
		int sample_rate = 44100,
		AVSampleFormat sample_fmt = AV_SAMPLE_FMT_FLT);

	void free_filters();

	AVFrame* convert_filters_frame(AVFrame* frame);

	void set_pcm_format(AVCodecContext* p_codec_context);

	// get audio information
	const double get_duration(); // 不能修改返回数据

	// reset audio sampler
	void reset_audio_sampler_SoundTouch(
		AVChannelLayout st_layout = AV_CHANNEL_LAYOUT_MONO,
		int out_sample_rate = 44100,
		AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_FLT);

	void reset_audio_sampler_output(
		AVChannelLayout out_layout = AV_CHANNEL_LAYOUT_MONO,
		int out_sample_rate = 44100,
		AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16);

	// save resampled audio to file
	void save_resampled_audio(const char* output_filename = "output.pcm");

	// iterate function for audio
	void seek(int64_t pos);
	AVFrame* next_audio_out_frame();

	// operator overloading
	//MusicReader& operator=(const MusicReader&) = delete;

	//void SomeInitFunction(AVSampleFormat sample_fmt, int sample_rate, int channels);

	// 调整滤镜
	//void adjust_filters(float bass, float mid, float treble);


//signals: // signals
	//void open_pcm_file_error(); // �� pcm �ļ������ź�


private: // private functions
	// Initialize ffmpeg
	char init_ffmpeg_audio(const std::string& filename);


public: // public variables
	// iterate sample count control
	//int per_channel_out_samples_count;
	AVFormatContext* p_format_context; // 格式上下文
	AVCodecContext*  p_codec_context; // 编码器上下文
	AVStream*		 p_audio_stream; // 音频流
	AVCodecContext*  p_resample_context; // 音频重采样上下文
	SwrContext*		 p_swr_context_SoundTouch; // SoundTouch 音频重采样上下文
	SwrContext*		 p_swr_context_output; // 输出音频重采样上下文

	AVChannelLayout  my_stereo_layout;
	int				 my_out_sample_rate;
	AVSampleFormat	 my_out_sample_fmt;
	//int64_t			 current_frame_position; // 当前帧位置
	// SoundTouch 音频处理参数
	AVChannelLayout  st_stereo_layout;
	int				 st_out_sample_rate;
	AVSampleFormat	 st_out_sample_fmt; // float for SoundTouch

	// 音频过滤器
	AVFilterGraph* filter_graph;
	AVFilterContext* buffersrc_ctx;
	AVFilterContext* buffersink_ctx;
	//AVAudioFifo* fifo = nullptr; // 音频过滤器缓冲区
	//AVFrame* p_frame = nullptr;
	//AVFrame* p_out_frame = nullptr;
	//AVPacket* packet = nullptr;


protected: // protected variables
	// 音频均衡器参数
	float bass_gain = 0.0f;
	float mid_gain = 0.0f;
	float treble_gain = 0.0f;


private: // private variables
	std::string		 audio_filename; // 音频文件名
	int				 audio_stream_index; // 音频流索引
	bool			 is_pcm; // 是否为 pcm 格式
	std::mutex		 reader_mutex; // 音频读取线程互斥量
};

#endif  // MusicReader
